package cn.nfwx.tv.controller;

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.IntentFilter;
import android.text.TextUtils;

import com.hdl.m3u8.M3U8InfoManger;
import com.hdl.m3u8.bean.M3U8;
import com.hdl.m3u8.bean.M3U8Ts;
import com.hdl.m3u8.bean.OnM3U8InfoListener;
import com.trello.rxlifecycle2.LifecycleTransformer;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.lang.ref.WeakReference;
import java.util.List;

import cn.nfwx.tv.base.BaseActivity;
import cn.nfwx.tv.db.AppDatabase;
import cn.nfwx.tv.db.DownProgramDao;
import cn.nfwx.tv.db.DownProgramModel;
import cn.nfwx.tv.db.TsDao;
import cn.nfwx.tv.db.TsProgramModel;
import cn.nfwx.tv.down.DownloadHelper;
import cn.nfwx.tv.helper.ValueCallback;
import cn.nfwx.tv.model.TvProgram;
import cn.nfwx.tv.util.GlideUtil;
import cn.nfwx.tv.util.LogUtil;
import cn.nfwx.tv.util.ToastUtil;
import io.reactivex.Observable;
import io.reactivex.ObservableEmitter;
import io.reactivex.ObservableOnSubscribe;
import io.reactivex.Observer;
import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.annotations.NonNull;
import io.reactivex.disposables.Disposable;
import io.reactivex.schedulers.Schedulers;

public class DownloadM3u8Controller {

    private static String TAG = DownloadM3u8Controller.class.getSimpleName();

    private static DownloadM3u8Controller instance;
    private final DownloadHelper mDownloadHelper;

    public static final String DOWNLOAD_ACTION = "download_helper_action";

    public static DownloadM3u8Controller getInstance() {
        if (instance == null) {
            synchronized (DownloadM3u8Controller.class) {
                if (instance == null) {
                    instance = new DownloadM3u8Controller();
                }
            }
        }
        return instance;
    }

    public DownloadM3u8Controller() {
        mDownloadHelper = DownloadHelper.getInstance();
    }

    private String getM3u8Path(Context context, TvProgram tvProgram) {
        String directoryPath = context.getFilesDir().getAbsolutePath() + File.separator + "movie" + File.separator + tvProgram.getTime();
        File dir = new File(directoryPath);
        if (!dir.exists()) {
            dir.mkdirs();
        }
        return directoryPath;
    }

    /**
     * 开启下载
     *
     * @param context
     * @param tvProgram
     * @param transformer
     */
    public synchronized void download(final Context context, final TvProgram tvProgram, final LifecycleTransformer<Integer> transformer, final ValueCallback<Integer> valueCallback) {
        if (!TextUtils.isEmpty(tvProgram.getUrl())) {
            if (!AppDatabase.getInstance(context).programDao().queryAllByUrl(tvProgram.getUrl()).isEmpty()) {
                ToastUtil.show(context, "已经下载中");
                return;
            }
            try {
                final WeakReference<ValueCallback<Integer>> weakReference = new WeakReference<>(valueCallback);
                M3U8InfoManger.getInstance().getM3U8Info(tvProgram.getUrl(), new OnM3U8InfoListener() {
                    @Override
                    public void onSuccess(final M3U8 m3U8) {
                        Observable.create(new ObservableOnSubscribe<Integer>() {
                            @Override
                            public void subscribe(ObservableEmitter<Integer> e) {
                                if (m3U8 == null) {
                                    e.onNext(DownProgramModel.STATS_FAIL);
                                    e.onComplete();
                                    return;
                                }
                                DownProgramDao programDao = AppDatabase.getInstance(context).programDao();
                                if (!programDao.queryAllByUrl(tvProgram.getUrl()).isEmpty()) {
                                    e.onNext(DownProgramModel.STATS_DOWNLOADED);
                                    e.onComplete();
                                    return;
                                }
                                final String basePath = getM3u8Path(context, tvProgram);
                                final String m3u8Path = basePath + File.separator + tvProgram.getProgram_name().replace("/", "") + ".mp4";
                                final String m3u8Url = tvProgram.getUrl();
                                final String imagePath = basePath + File.separator + tvProgram.getProgram_name().replace("/", "") + ".jpg";
                                final String imageUrl = tvProgram.getUrl().replace(".m3u8", ".jpg");

                                GlideUtil.downloadImage(context, imageUrl, 8, 6, new ValueCallback<File>() {
                                    @Override
                                    public void onReceiveValue(File file) {
                                        FileOutputStream fileOutputStream = null;
                                        FileInputStream fileInputStream = null;
                                        try {
                                            File outPutFile = new File(imagePath);
                                            if (outPutFile.exists()) {
                                                outPutFile.delete();
                                            }
                                            outPutFile.createNewFile();
                                            fileOutputStream = new FileOutputStream(outPutFile);
                                            if (file.exists()) {
                                                fileInputStream = new FileInputStream(file);
                                                int length = 0;
                                                byte[] data = new byte[1024];
                                                while ((length = fileInputStream.read(data)) != -1) {
                                                    fileOutputStream.write(data, 0, length);
                                                }
                                            }
                                            fileOutputStream.flush();
                                        } catch (FileNotFoundException e) {
                                            e.printStackTrace();
                                        } catch (IOException e) {
                                            e.printStackTrace();
                                        } finally {
                                            try {
                                                if (fileOutputStream != null) {
                                                    fileOutputStream.close();
                                                }
                                                if (fileInputStream != null) {
                                                    fileInputStream.close();
                                                }
                                            } catch (IOException e) {
                                                e.printStackTrace();
                                            }
                                        }
                                    }
                                });

                                DownProgramModel programModel = new DownProgramModel(tvProgram.getProgram_name(),
                                        tvProgram.getTime(), tvProgram.getUrl(), basePath, m3u8Path, imagePath, DownProgramModel.STATS_DEFAULT, m3U8.getTsList().size());
                                final long programId = programDao.insert(programModel);
                                e.onNext(DownProgramModel.STATS_DEFAULT);
                                try {
                                    TsDao tsDao = AppDatabase.getInstance(context).tsDao();
                                    TsProgramModel[] tsProgramModels = new TsProgramModel[m3U8.getTsList().size()];
                                    for (int i = 0; i < m3U8.getTsList().size(); i++) {
                                        M3U8Ts m3U8Ts = m3U8.getTsList().get(i);
                                        String m3U8tsPath = basePath + File.separator + m3U8Ts.getFileName();
                                        String tsUrl;
                                        if ("http".equals(m3U8Ts.getFile().substring(0, 4))) {
                                            tsUrl = m3U8Ts.getFile();
                                        } else {
                                            tsUrl = m3U8.getBasepath() + m3U8Ts.getFile();
                                        }
                                        TsProgramModel tsProgramModel = new TsProgramModel(m3u8Url, tsUrl, m3U8tsPath, TsProgramModel.STATS_NO, tsUrl);
                                        tsProgramModel.setProgramId(programId);
                                        tsProgramModels[i] = tsProgramModel;
                                    }
                                    tsDao.insert(tsProgramModels);
                                    mDownloadHelper.addTask(tvProgram.getProgram_name(), tvProgram.getTime(), m3u8Url, basePath, m3u8Path, null, DOWNLOAD_ACTION).submit(context);
                                    e.onComplete();
                                } catch (Exception e1) {
                                    List<DownProgramModel> programModels = programDao.queryAllByUrl(m3u8Url);
                                    if (!programModels.isEmpty()) {
                                        DownProgramModel program = programModels.get(0);
                                        File file = new File(program.getBasePath());
                                        if (file.exists()) {
                                            file.delete();
                                        }
                                        programDao.delete(program);
                                    }
                                    e.onNext(DownProgramModel.STATS_FAIL);
                                    e.onComplete();
                                }
                            }
                        }).subscribeOn(Schedulers.io())
                                .observeOn(AndroidSchedulers.mainThread())
                                .compose(transformer)
                                .subscribe(new Observer<Integer>() {
                                    @Override
                                    public void onSubscribe(Disposable d) {
                                    }

                                    @Override
                                    public void onNext(Integer integer) {
                                        ValueCallback<Integer> valueCallback = weakReference.get();
                                        if (valueCallback != null) {
                                            valueCallback.onReceiveValue(integer);
                                        }
                                    }

                                    @Override
                                    public void onError(Throwable e) {
                                    }

                                    @Override
                                    public void onComplete() {
                                    }
                                });
                    }

                    @Override
                    public void onStart() {

                    }

                    @Override
                    public void onError(Throwable errorMsg) {
                        ValueCallback<Integer> valueCallback = weakReference.get();
                        if (valueCallback != null) {
                            valueCallback.onReceiveValue(DownProgramModel.STATS_FAIL);
                        }
                    }
                });
            } catch (Exception e) {
                if (valueCallback != null) {
                    valueCallback.onReceiveValue(DownProgramModel.STATS_FAIL);
                }
            }
        }
    }

    /**
     * 暂停下载
     *
     * @param context
     * @param m3u8Url
     */
    public synchronized void pause(final Context context, final String m3u8Url) {
        Observable.create(new ObservableOnSubscribe<DownProgramModel>() {
            @Override
            public void subscribe(ObservableEmitter<DownProgramModel> e) {
                DownProgramDao downProgramDao = AppDatabase.getInstance(context).programDao();
                List<DownProgramModel> downProgramModels = downProgramDao.queryAllByUrl(m3u8Url);
                if (!downProgramModels.isEmpty()) {
                    DownProgramModel downProgramModel = downProgramModels.get(0);
                    e.onNext(downProgramModel);
                    e.onComplete();
                }
            }
        }).subscribe(new Observer<DownProgramModel>() {
            @Override
            public void onSubscribe(Disposable d) {
            }

            @Override
            public void onNext(DownProgramModel downProgramModel) {
                mDownloadHelper.pauseTask(downProgramModel.getProgramName(), downProgramModel.getProgramTime(), downProgramModel.getDownloadUrl(), downProgramModel.getBasePath(), downProgramModel.getLocalPath(), DOWNLOAD_ACTION);
            }

            @Override
            public void onError(Throwable e) {

            }

            @Override
            public void onComplete() {
                mDownloadHelper.submit(context);
            }
        });
//        DownProgramDao downProgramDao = AppDatabase.getInstance(context).programDao();
//        List<DownProgramModel> downProgramModels = downProgramDao.queryAllByUrl(m3u8Url);
//        if (!downProgramModels.isEmpty()) {
//            DownProgramModel downProgramModel = downProgramModels.get(0);
//            mDownloadHelper.pauseTask(downProgramModel.getProgramName(), downProgramModel.getProgramTime(), downProgramModel.getDownloadUrl(), downProgramModel.getBasePath(), downProgramModel.getLocalPath(), DOWNLOAD_ACTION).submit(context);
//        }
    }

    /**
     * 开始下载
     *
     * @param context
     * @param m3u8Url
     */
    public synchronized void start(final Context context, final String m3u8Url) {
        Observable.create(new ObservableOnSubscribe<DownProgramModel>() {
            @Override
            public void subscribe(ObservableEmitter<DownProgramModel> e) throws Exception {
                if (!TextUtils.isEmpty(m3u8Url)) {
                    DownProgramDao downProgramDao = AppDatabase.getInstance(context).programDao();
//            final DownProgramDao downProgramDao = new DownProgramDao(context);
                    List<DownProgramModel> downProgramModels = downProgramDao.queryAllByUrl(m3u8Url);
                    if (!downProgramModels.isEmpty()) {
                        DownProgramModel downProgramModel = downProgramModels.get(0);
                        e.onNext(downProgramModel);
                        e.onComplete();
                    }
                }
            }
        }).subscribe(new Observer<DownProgramModel>() {
            @Override
            public void onSubscribe(Disposable d) {

            }

            @Override
            public void onNext(DownProgramModel downProgramModel) {
                try {
                    mDownloadHelper.addTask(downProgramModel.getProgramName(), downProgramModel.getProgramTime(), m3u8Url, downProgramModel.getBasePath(), downProgramModel.getDownloadUrl(), null, DOWNLOAD_ACTION);
                } catch (Exception e) {
                    AppDatabase.getInstance(context).programDao().delete(downProgramModel);
                    File file = new File(downProgramModel.getBasePath());
                    if (file.exists()) {
                        file.delete();
                    }
                    ToastUtil.show(context, "下载失败---");
                }
            }

            @Override
            public void onError(Throwable e) {

            }

            @Override
            public void onComplete() {
                mDownloadHelper.submit(context);
            }
        });
//        if (!TextUtils.isEmpty(m3u8Url)) {
//            DownProgramDao downProgramDao = AppDatabase.getInstance(context).programDao();
////            final DownProgramDao downProgramDao = new DownProgramDao(context);
//            List<DownProgramModel> downProgramModels = downProgramDao.queryAllByUrl(m3u8Url);
//            if (!downProgramModels.isEmpty()) {
//                DownProgramModel downProgramModel = downProgramModels.get(0);
//                try {
//                    mDownloadHelper.addTask(downProgramModel.getProgramName(), downProgramModel.getProgramTime(), m3u8Url, downProgramModel.getBasePath(), downProgramModel.getDownloadUrl(), null, DOWNLOAD_ACTION).submit(context);
//                } catch (Exception e) {
//                    List<DownProgramModel> programModels = downProgramDao.queryAllByUrl(m3u8Url);
//                    if (!programModels.isEmpty()) {
//                        DownProgramModel program = programModels.get(0);
//                        downProgramDao.delete(program);
//                        File file = new File(program.getBasePath());
//                        if (file.exists()) {
//                            file.delete();
//                        }
//                    }
//                    ToastUtil.show(context, "下载失败---");
//                }
//            }
//        }
    }

    /**
     * 暂停全部
     *
     * @param context
     */
    public synchronized void pauseAll(final Context context) {
//        DownProgramDao dao = new DownProgramDao(context);
//        DownProgramDao downProgramDao = AppDatabase.getInstance(context).programDao();
//        List<DownProgramModel> downProgramModels = downProgramDao.queryForAll();
//        for (DownProgramModel program : downProgramModels) {
//            if (program.getStats() == DownProgramModel.STATS_DOWNLOADING
//                    || program.getStats() == DownProgramModel.STATS_DEFAULT
//                    || program.getStats() == DownProgramModel.STATS_WAIT) {
//                mDownloadHelper.pauseTask(program.getProgramName(), program.getProgramTime(), program.getDownloadUrl(), program.getBasePath(), program.getLocalPath(), DOWNLOAD_ACTION);
//            }
//        }
//        mDownloadHelper.submit(context);


        Observable.create(new ObservableOnSubscribe<DownProgramModel>() {
            @Override
            public void subscribe(@NonNull ObservableEmitter<DownProgramModel> e) {
                DownProgramDao downProgramDao = AppDatabase.getInstance(context).programDao();
                List<DownProgramModel> downProgramModels = downProgramDao.queryForAll();
                for (DownProgramModel program : downProgramModels) {
                    if (program.getStats() == DownProgramModel.STATS_DOWNLOADING
                            || program.getStats() == DownProgramModel.STATS_DEFAULT
                            || program.getStats() == DownProgramModel.STATS_WAIT) {
                        e.onNext(program);
                    }
                }
                e.onComplete();
            }
        }).subscribe(new Observer<DownProgramModel>() {
            @Override
            public void onSubscribe(@NonNull Disposable d) {
            }

            @Override
            public void onNext(@NonNull DownProgramModel program) {
                mDownloadHelper.pauseTask(program.getProgramName(), program.getProgramTime(), program.getDownloadUrl(), program.getBasePath(), program.getLocalPath(), DOWNLOAD_ACTION);
            }

            @Override
            public void onError(@NonNull Throwable e) {
            }

            @Override
            public void onComplete() {
                mDownloadHelper.submit(context);
            }
        });
    }

    /**
     * 开始全部
     */
    public void startAll(BaseActivity mActivity) {
        DownProgramDao downProgramDao = AppDatabase.getInstance(mActivity).programDao();
        List<DownProgramModel> downProgramModels = downProgramDao.queryForAll();
        for (DownProgramModel program : downProgramModels) {
            if (program.getStats() == DownProgramModel.STATS_PAUSE) {
                start(mActivity, program.getDownloadUrl());
            }
        }
    }

    /**
     * 暂停全部
     *
     * @param m3u8Urls
     */
    public void pauseAll(Context context, List<String> m3u8Urls) {
        DownProgramDao downProgramDao = AppDatabase.getInstance(context).programDao();
        for (String m3u8Url : m3u8Urls) {
//            final DownProgramDao downProgramDao = new DownProgramDao(context);
            List<DownProgramModel> downProgramModels = downProgramDao.queryAllByUrl(m3u8Url);
            if (!downProgramModels.isEmpty()) {
                DownProgramModel downProgramModel = downProgramModels.get(0);
                mDownloadHelper.pauseTask(downProgramModel.getProgramName(), downProgramModel.getProgramTime(), downProgramModel.getDownloadUrl(), downProgramModel.getBasePath(), downProgramModel.getLocalPath(), DOWNLOAD_ACTION);
            }
        }
        mDownloadHelper.submit(context);
    }

    /**
     * 开启全部
     *
     * @param m3u8Urls
     */
    public void startAll(Context context, List<String> m3u8Urls) {
        DownProgramDao downProgramDao = AppDatabase.getInstance(context).programDao();
        for (String m3u8Url : m3u8Urls) {
            if (!TextUtils.isEmpty(m3u8Url)) {
//                final DownProgramDao downProgramDao = new DownProgramDao(context);
                List<DownProgramModel> downProgramModels = downProgramDao.queryAllByUrl(m3u8Url);
                if (!downProgramModels.isEmpty()) {
                    DownProgramModel downProgramModel = downProgramModels.get(0);
                    try {
                        mDownloadHelper.addTask(downProgramModel.getProgramName(), downProgramModel.getProgramTime(), m3u8Url, downProgramModel.getBasePath(), downProgramModel.getDownloadUrl(), null, DOWNLOAD_ACTION);
                    } catch (Exception e) {
                        List<DownProgramModel> programModels = downProgramDao.queryAllByUrl(m3u8Url);
                        if (!programModels.isEmpty()) {
                            DownProgramModel program = programModels.get(0);
                            downProgramDao.delete(program);
                            File file = new File(program.getBasePath());
                            if (file.exists()) {
                                file.delete();
                            }
                        }
                        ToastUtil.show(context, "下载失败---");
                    }
                }
            }
        }
        mDownloadHelper.submit(context);
    }

    /**
     * 更新状态信息
     */
    public void refreshAll(final Context context) {
//        DownProgramDao dao = new DownProgramDao(context);
        Observable.create(new ObservableOnSubscribe<DownProgramModel>() {
            @Override
            public void subscribe(@NonNull ObservableEmitter<DownProgramModel> e) {
                DownProgramDao downProgramDao = AppDatabase.getInstance(context).programDao();
                List<DownProgramModel> downProgramModels = downProgramDao.queryForAll();
                for (DownProgramModel downProgramModel : downProgramModels) {
                    if (downProgramModel.getStats() != DownProgramModel.STATS_SUCCESS && downProgramModel.getStats() != DownProgramModel.STATS_PAUSE) {
                        e.onNext(downProgramModel);
                    }
                }
                e.onComplete();
            }
        }).subscribe(new Observer<DownProgramModel>() {
            @Override
            public void onSubscribe(@NonNull Disposable d) {
            }

            @Override
            public void onNext(@NonNull DownProgramModel downProgramModel) {
                mDownloadHelper.refreshTask(downProgramModel.getProgramName(), downProgramModel.getProgramTime(), downProgramModel.getDownloadUrl(), downProgramModel.getBasePath(), downProgramModel.getLocalPath(), DOWNLOAD_ACTION);
            }

            @Override
            public void onError(@NonNull Throwable e) {
            }

            @Override
            public void onComplete() {
                mDownloadHelper.submit(context);
            }
        });
    }

    /**
     * 返回状态
     *
     * @param context
     * @param m3u8url
     * @return
     */
    public int getProgramStats(Context context, String m3u8url) {
        DownProgramDao downProgramDao = AppDatabase.getInstance(context).programDao();
        List<DownProgramModel> downProgramModels = downProgramDao.queryAllByUrl(m3u8url);
        if (!downProgramModels.isEmpty()) {
            return downProgramModels.get(0).getStats();
        }
        return -1;
    }

    /**
     * 注册广播
     *
     * @param context
     */
    public void registerDownloadReceiver(Context context, BroadcastReceiver downloadReceiver) {
        try {
            IntentFilter intentFilter = new IntentFilter(DOWNLOAD_ACTION);
            context.registerReceiver(downloadReceiver, intentFilter);
        } catch (Exception e) {

        }
    }

    /**
     * 注销广播
     *
     * @param context
     */
    public void unRegisterDownloadReceiver(Context context, BroadcastReceiver downloadReceiver) {
        try {
            context.unregisterReceiver(downloadReceiver);
        } catch (Exception e) {

        }
    }
}
